package com.cal.utms.model.maintenance;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import com.cal.utms.action.user_maintenance.LoginAction;
import com.cal.utms.dao.maintenance.CustodianDao;
import com.cal.utms.dao.maintenance.DealTypeDao;
import com.cal.utms.dao.maintenance.IssuerDaoImpl;
import com.cal.utms.dao.maintenance.NewFundDao;
import com.cal.utms.dao.user_maintenance.UserDaoImpl;
import com.cal.utms.dto.maintenance.NewFundDto;
import com.cal.utms.entity.CustodianContactPerson;
import com.cal.utms.entity.DealType;
import com.cal.utms.entity.Fund;
import com.cal.utms.entity.FundInstrumentMap;
import com.cal.utms.entity.IssuerType;

public class NewFundModel {
	SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
	DecimalFormat amountFormatter = new DecimalFormat("#,###.00");
	DecimalFormat valueFormatter = new DecimalFormat("#,###.0000");

	public Fund createEntity(NewFundDto newFundDto) {
		Fund fund = new Fund();

		fund.setStatus("Initial");
		fund.setCreatedBy(LoginAction.getCurrentLogingUser().getUserName());
		fund.setCreatedDate(new Date());
		this.mapDtoFund(newFundDto, fund);
		return fund;
	}

	public NewFundDto decodeEntity(Fund fund) {
		String ccPersons = "";
		String purchasableIns = "";
		String salableIns = "";
		String repoableIns = "";
		String rRepoableIns = "";
		String fdIssuers = "";
		DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
		NumberFormat nf = new DecimalFormat("###,###.####");
		NewFundDto newFundDto = new NewFundDto();
		newFundDto.setId(fund.getId());
		newFundDto.setName(fund.getFundName());
		newFundDto.setCode(fund.getFundCode());
		if (fund.getTrustDeedDate() != null) {
			newFundDto.setTrustDeedDate(dateFormat.format(fund.getTrustDeedDate()));
		}
		newFundDto.setFundManagerId(fund.getFundManager().getId());
		newFundDto.setCdsAccount(fund.getCdsAccount());
		newFundDto.setDescription(fund.getDescription());
		newFundDto.setCustodianId(fund.getCustodian().getId());
		newFundDto.setAccountNo(fund.getCustodianAccount());
		if (fund.getCustodianContactPersons() != null) {
			for (CustodianContactPerson ccp : fund.getCustodianContactPersons()) {
				ccPersons = ccPersons + ccp.getId() + "," + ccp.getName() + "," + ccp.getDesignation() + "," + ccp.getPhone() + "," + ccp.getFax() + "," + ccp.getEmail() + ";";
			}
			newFundDto.setCustodianContactPersons(ccPersons);
		}
		newFundDto.setFundCategory(fund.getCategory());
		newFundDto.setValuationMethod(fund.getValuationMethod());
		if (fund.getDealTypes() != null) {
			for (DealType dealType : fund.getDealTypes()) {
				if (dealType.getCode().equals("PURCH")) {
					newFundDto.setPurchaseDeals(true);
				} else if (dealType.getCode().equals("SALE")) {
					newFundDto.setSaleDeals(true);
				} else if (dealType.getCode().equals("FD")) {
					newFundDto.setFdDeals(true);
				} else if (dealType.getCode().equals("REPO")) {
					newFundDto.setRepoDeals(true);
				} else if (dealType.getCode().equals("RREPO")) {
					newFundDto.setRevRepoDeals(true);
				} else {
					System.out.println("Invalid Deal code:" + dealType.getCode());
				}
			}
		}
		if (fund.getFundInstrumentMaps() != null) {
			for (FundInstrumentMap fiMap : fund.getFundInstrumentMaps()) {
				if (fiMap.getDealTypeBean().getCode().equals("PURCH")) {
					purchasableIns = purchasableIns + fiMap.getInstrumentTypeId() + ";";
				} else if (fiMap.getDealTypeBean().getCode().equals("SALE")) {
					salableIns = salableIns + fiMap.getInstrumentTypeId() + ";";
				} else if (fiMap.getDealTypeBean().getCode().equals("REPO")) {
					repoableIns = repoableIns + fiMap.getInstrumentTypeId() + ";";
				} else if (fiMap.getDealTypeBean().getCode().equals("RREPO")) {
					rRepoableIns = rRepoableIns + fiMap.getInstrumentTypeId() + ";";
				} else {
					System.out.println("Invalid Deal Code:" + fiMap.getDealTypeBean().getCode());
				}
			}
			newFundDto.setPurchasableIns(purchasableIns);
			newFundDto.setSalableIns(salableIns);
			newFundDto.setRepoableIns(repoableIns);
			newFundDto.setRRepoableIns(rRepoableIns);
		}
		if (fund.getIssureTypes() != null) {
			for (IssuerType issuerType : fund.getIssureTypes()) {
				System.out.println(issuerType.getIssureCategory());
				fdIssuers = fdIssuers + issuerType.getId() + ";";
			}
			newFundDto.setFdIssuers(fdIssuers);
		}
		if (fund.getCustodianFeeType().equals("percent")) {
			newFundDto.setCustFeeMethod(fund.getCustodianFeeType());
			if (fund.getCustodianFee() != null)
				newFundDto.setCustFeePercent(fund.getCustodianFee().toString());
		} else {
			String a[] = fund.getCustodianFeeType().split(",");
			newFundDto.setCustFeeMethod(a[0]);
			newFundDto.setCustFeeFreq(a[1]);
			if (fund.getCustodianFee() != null)
				newFundDto.setCustFeeAmount(amountFormatter.format(fund.getCustodianFee()));
		}

		if (fund.getTrusteeFeeType().equals("percent")) {
			newFundDto.setTrusteeFeeMethod(fund.getTrusteeFeeType());
			if (fund.getTrusteeFee() != null)
				newFundDto.setTrusteeFeePercent(fund.getTrusteeFee().toString());
		} else {
			String a[] = fund.getTrusteeFeeType().split(",");
			newFundDto.setTrusteeFeeMethod(a[0]);
			newFundDto.setTrusteeFeeFreq(a[1]);
			if (fund.getTrusteeFee() != null)
				newFundDto.setTrusteeFeeAmount(amountFormatter.format(fund.getTrusteeFee()));
		}

		if (fund.getManagementFeeType().equals("percent")) {
			newFundDto.setManageFeeMethod(fund.getManagementFeeType());
			if (fund.getManagementFee() != null)
				newFundDto.setManageFeePercent(fund.getManagementFee().toString());
		} else {
			String a[] = fund.getManagementFeeType().split(",");
			newFundDto.setManageFeeMethod(a[0]);
			newFundDto.setManageFeeFreq(a[1]);
			if (fund.getManagementFee() != null)
				newFundDto.setManageFeeAmount(amountFormatter.format(fund.getManagementFee()));
		}

		if (fund.getAuditFeeType().equals("percent")) {
			newFundDto.setAuditFeeMethod(fund.getAuditFeeType());
			if (fund.getAuditFee() != null)
				newFundDto.setAuditFeePercent(fund.getAuditFee().toString());
		} else {
			String a[] = fund.getAuditFeeType().split(",");
			newFundDto.setAuditFeeMethod(a[0]);
			newFundDto.setAuditFeeFreq(a[1]);
			if (fund.getAuditFee() != null)
				newFundDto.setAuditFeeAmount(amountFormatter.format(fund.getAuditFee()));
		}

		if (fund.getOpc() != null)
			newFundDto.setOutboundCharge(fund.getOpc().doubleValue());

		if (fund.getOtherFeePercent() != null)
			newFundDto.setOtherPercentageFee(fund.getOtherFeePercent().doubleValue());

		if (fund.getOtherFeeAnnual() != null)
			newFundDto.setFixedAnnualFee(fund.getOtherFeeAnnual().toString());

		if (fund.getOtherFeeMonthly() != null)
			newFundDto.setFixedMonthlyFee(fund.getOtherFeeMonthly().toString());

		// if(fund.getMinUnitHolders()!=null)
		newFundDto.setMinUnitHolders(fund.getMinUnitHolders());

		if (fund.getMaxPercentage() != null)
			newFundDto.setMaxInvestPercent(fund.getMaxPercentage().doubleValue());

		if (fund.getMinPercentage() != null)
			newFundDto.setMinLiquidityPercent(fund.getMinPercentage().doubleValue());

		newFundDto.setStatus(fund.getStatus());
		newFundDto.setCreatedBy(fund.getCreatedBy());
		newFundDto.setCreatedDate(df.format(fund.getCreatedDate()));
		newFundDto.setConfirmedBy(fund.getConfirmedBy());
		if (fund.getConfirmedDate() != null)
			newFundDto.setConfirmedDate(df.format(fund.getConfirmedDate()));
		newFundDto.setModifiedBy(fund.getModifiedBy());
		if (fund.getModifiedDate() != null)
			newFundDto.setModifiedDate(df.format(fund.getModifiedDate()));

		if (fund.getUnitValue() != null) {
			newFundDto.setUnitVal(nf.format(fund.getUnitValue()));
		}
		if (fund.getPortfolio() != null) {
			newFundDto.setPortFolioVal(nf.format(fund.getPortfolio()));
		}
		if (fund.getUpdateDate() != null) {
			newFundDto.setUpdateDate(df.format(fund.getUpdateDate()));
		}

		newFundDto.setSuccess(true);

		return newFundDto;
	}

	public Fund confirmEntity(NewFundDto newFundDto, Fund fund) {

		Date date = new Date();

		this.mapDtoFund(newFundDto, fund);
		fund.setStatus("Confirmed");
		fund.setConfirmedBy(newFundDto.getConfirmedBy());
		fund.setConfirmedDate(date);
		fund.setModifiedBy(LoginAction.getCurrentLogingUser().getUserName());
		fund.setModifiedDate(date);
		return fund;
	}

	public Fund updateEntity(NewFundDto newFundDto, Fund fund) {
		Date date = new Date();

		this.mapDtoFund(newFundDto, fund);

		fund.setModifiedBy(LoginAction.getCurrentLogingUser().getUserName());
		fund.setModifiedDate(date);
		return fund;
	}

	public static void main(String[] args) throws ParseException {
		NumberFormat format = NumberFormat.getInstance();
		Number number = format.parse("120,000,000.00150");
		double d = number.doubleValue();
		System.out.println(d);
	}

	public Fund mapDtoFund(NewFundDto newFundDto, Fund fund) {

		UserDaoImpl userDaoImpl = new UserDaoImpl();
		CustodianDao custodianDao = new CustodianDao();
		NumberFormat format = NumberFormat.getInstance();
		Number number;
		List<CustodianContactPerson> ccpList = new ArrayList<CustodianContactPerson>();
		List<FundInstrumentMap> fundInsMapList = new ArrayList<FundInstrumentMap>();
		DealTypeDao dealTypeDao = new DealTypeDao();
		List<DealType> dealTypes = new ArrayList<DealType>();
		List<IssuerType> fdIssures = new ArrayList<IssuerType>();
		IssuerDaoImpl issureDao = new IssuerDaoImpl();

		fund.setId(newFundDto.getId());
		fund.setFundName(newFundDto.getName());
		fund.setFundCode(newFundDto.getCode());
		fund.setFundManager(userDaoImpl.getById(newFundDto.getFundManagerId()));
		fund.setCdsAccount(newFundDto.getCdsAccount());
		fund.setDescription(newFundDto.getDescription());
		fund.setCategory(newFundDto.getFundCategory());
		fund.setMinUnitHolders(newFundDto.getMinUnitHolders());
		fund.setMaxPercentage(new BigDecimal(newFundDto.getMaxInvestPercent()));
		fund.setMinPercentage(new BigDecimal(newFundDto.getMinLiquidityPercent()));
		fund.setCustodian(custodianDao.getById(newFundDto.getCustodianId()));
		fund.setCustodianAccount(newFundDto.getAccountNo());
		fund.setValuationMethod(newFundDto.getValuationMethod());
		fund.setOpc(new BigDecimal(newFundDto.getOutboundCharge()));
		if (newFundDto.getTrustDeedDate() != null) {
			try {
				fund.setTrustDeedDate(dateFormat.parse(newFundDto.getTrustDeedDate()));
			} catch (ParseException e1) {
				e1.printStackTrace();
			}
		}

		if (newFundDto.getCustFeeMethod().equals("fixed")) {
			fund.setCustodianFeeType(newFundDto.getCustFeeMethod() + "," + newFundDto.getCustFeeFreq());
			try {
				number = format.parse(newFundDto.getCustFeeAmount());
				fund.setCustodianFee(new BigDecimal(number.doubleValue()));
			} catch (ParseException e) {
				System.out.println("Error in parsing custodian Fee1" + newFundDto.getCustFeeAmount());
			}
		} else {
			fund.setCustodianFeeType(newFundDto.getCustFeeMethod());
			try {
				number = format.parse(newFundDto.getCustFeePercent());
				fund.setCustodianFee(new BigDecimal(number.doubleValue()));
			} catch (ParseException e) {
				System.out.println("Error in parsing custodian Fee2:" + newFundDto.getCustFeePercent());
			}
		}

		if (newFundDto.getTrusteeFeeMethod().equals("fixed")) {
			fund.setTrusteeFeeType(newFundDto.getTrusteeFeeMethod() + "," + newFundDto.getTrusteeFeeFreq());
			try {
				number = format.parse(newFundDto.getTrusteeFeeAmount());
				fund.setTrusteeFee(new BigDecimal(number.doubleValue()));
			} catch (ParseException e) {
				System.out.println("Error in parsing custodian Fee1:" + newFundDto.getTrusteeFeeAmount());
			}
		} else {
			fund.setTrusteeFeeType(newFundDto.getTrusteeFeeMethod());
			try {
				number = format.parse(newFundDto.getTrusteeFeePercent());
				fund.setTrusteeFee(new BigDecimal(number.doubleValue()));
			} catch (ParseException e) {
				System.out.println("Error in parsing Trustee Fee2:" + newFundDto.getTrusteeFeePercent());
			}
		}

		if (newFundDto.getManageFeeMethod().equals("fixed")) {
			fund.setManagementFeeType(newFundDto.getManageFeeMethod() + "," + newFundDto.getManageFeeFreq());
			try {
				number = format.parse(newFundDto.getManageFeeAmount());
				fund.setManagementFee(new BigDecimal(number.doubleValue()));
			} catch (ParseException e) {
				System.out.println("Error in parsing Management Fee1:" + newFundDto.getManageFeeAmount());
			}
		} else {
			fund.setManagementFeeType(newFundDto.getManageFeeMethod());
			try {
				number = format.parse(newFundDto.getManageFeePercent());
				fund.setManagementFee(new BigDecimal(number.doubleValue()));
			} catch (ParseException e) {
				System.out.println("Error in parsing Management Fee2:" + newFundDto.getManageFeePercent());
			}
		}

		if (newFundDto.getAuditFeeMethod().equals("fixed")) {
			fund.setAuditFeeType(newFundDto.getAuditFeeMethod() + "," + newFundDto.getAuditFeeFreq());
			try {
				number = format.parse(newFundDto.getAuditFeeAmount());
				fund.setAuditFee(new BigDecimal(number.doubleValue()));
			} catch (ParseException e) {
				System.out.println("Error in parsing Audit Fee1:" + newFundDto.getAuditFeeAmount());
			}
		} else {
			fund.setAuditFeeType(newFundDto.getAuditFeeMethod());
			try {
				number = format.parse(newFundDto.getAuditFeePercent());
				fund.setAuditFee(new BigDecimal(number.doubleValue()));
			} catch (ParseException e) {
				System.out.println("Error in parsing Audit Fee2:" + newFundDto.getAuditFeeMethod());
			}
		}
		try {
			number = format.parse(newFundDto.getFixedAnnualFee());
			fund.setOtherFeeAnnual(new BigDecimal(number.doubleValue()));
		} catch (ParseException e) {
			System.out.println("Error in parsing Fixed annual Fee:" + newFundDto.getFixedAnnualFee());
		}
		try {
			number = format.parse(newFundDto.getFixedMonthlyFee());
			fund.setOtherFeeMonthly(new BigDecimal(number.doubleValue()));
		} catch (ParseException e) {
			System.out.println("Error in parsing Fixed monthly Fee: " + newFundDto.getFixedMonthlyFee());
		}
		fund.setOtherFeePercent(new BigDecimal(newFundDto.getOtherPercentageFee()));

		try {
			number = format.parse(newFundDto.getUnitVal());
			fund.setUnitValue(new BigDecimal(number.doubleValue()));
		} catch (ParseException e) {
			System.out.println("Error in parsing Fixed monthly Fee: " + newFundDto.getFixedMonthlyFee());
		}

		if (newFundDto.getCustodianContactPersons() != null) {
			for (String r : newFundDto.getCustodianContactPersons().split(";")) {
				String[] fields = r.split(",");
				if (fields.length > 4) {
					CustodianContactPerson ccp = new CustodianContactPerson();
					ccp.setFund(fund);
					ccp.setName(fields[0]);
					ccp.setDesignation(fields[1]);
					ccp.setPhone(fields[2]);
					ccp.setFax(fields[3]);
					ccp.setEmail(fields[4]);
					ccpList.add(ccp);
				}
			}
		}
		fund.setCustodianContactPersons(ccpList);

		if (newFundDto.getPurchasableIns() != null && !newFundDto.getPurchasableIns().equals("")) {
			DealType dealType = dealTypeDao.getDealTypeList("Purch").get(0);
			for (String r : newFundDto.getPurchasableIns().split(";")) {
				FundInstrumentMap fundInsMap = new FundInstrumentMap();
				fundInsMap.setDealTypeBean(dealType);
				fundInsMap.setFund(fund);
				try {
					fundInsMap.setInstrumentTypeId(Integer.parseInt(r));
				} catch (NumberFormatException nfe) {
					System.out.println("Invalid Purchasable Instrument no:" + r);
					continue;
				}
				fundInsMapList.add(fundInsMap);
			}
		}

		if (newFundDto.getSalableIns() != null && !newFundDto.getSalableIns().equals("")) {
			DealType dealType = dealTypeDao.getDealTypeList("Sale").get(0);
			for (String r : newFundDto.getSalableIns().split(";")) {
				FundInstrumentMap fundInsMap = new FundInstrumentMap();
				fundInsMap.setDealTypeBean(dealType);
				fundInsMap.setFund(fund);
				try {
					fundInsMap.setInstrumentTypeId(Integer.parseInt(r));
				} catch (NumberFormatException nfe) {
					System.out.println("Invalid Salable Instrument no:" + r);
					continue;
				}
				fundInsMapList.add(fundInsMap);
			}
		}

		if (newFundDto.getRepoableIns() != null && !newFundDto.getRepoableIns().equals("")) {
			DealType dealType = dealTypeDao.getDealTypeList("Repo").get(0);
			for (String r : newFundDto.getRepoableIns().split(";")) {
				FundInstrumentMap fundInsMap = new FundInstrumentMap();
				fundInsMap.setDealTypeBean(dealType);
				fundInsMap.setFund(fund);
				try {
					fundInsMap.setInstrumentTypeId(Integer.parseInt(r));
				} catch (NumberFormatException nfe) {
					System.out.println("Invalid Repoable Instrument no:" + r);
					continue;
				}
				fundInsMapList.add(fundInsMap);
			}
		}

		if (newFundDto.getRRepoableIns() != null && !newFundDto.getRRepoableIns().equals("")) {
			DealType dealType = dealTypeDao.getDealTypeList("RevR").get(0);
			for (String r : newFundDto.getRRepoableIns().split(";")) {
				FundInstrumentMap fundInsMap = new FundInstrumentMap();
				fundInsMap.setDealTypeBean(dealType);
				fundInsMap.setFund(fund);
				try {
					fundInsMap.setInstrumentTypeId(Integer.parseInt(r));
				} catch (NumberFormatException nfe) {
					System.out.println("Invalid Repoable Instrument no:" + r);
					continue;
				}
				fundInsMapList.add(fundInsMap);
			}
		}
		fund.setFundInstrumentMaps(fundInsMapList);

		if (newFundDto.isPurchaseDeals()) {
			dealTypes.add(dealTypeDao.getDealTypeList("Purch").get(0));
		}
		if (newFundDto.isSaleDeals()) {
			dealTypes.add(dealTypeDao.getDealTypeList("Sale").get(0));
		}
		if (newFundDto.isFdDeals()) {
			dealTypes.add(dealTypeDao.getDealTypeList("Fix").get(0));
		}
		if (newFundDto.isRepoDeals()) {
			dealTypes.add(dealTypeDao.getDealTypeList("Repo").get(0));
		}
		if (newFundDto.isRevRepoDeals()) {
			dealTypes.add(dealTypeDao.getDealTypeList("RevR").get(0));
		}
		fund.setDealTypes(dealTypes);

		if (newFundDto.getFdIssuers() != null && !newFundDto.getFdIssuers().equals("")) {
			int issuerId = 0;
			IssuerType issuerType = null;
			for (String r : newFundDto.getFdIssuers().split(";")) {
				try {
					issuerId = Integer.parseInt(r);
				} catch (NumberFormatException nfe) {
					System.out.println("Invalid IssuerID found :" + r);
					continue;
				}
				issuerType = issureDao.getIssuerTypeById(issuerId);
				if (issuerType != null) {
					fdIssures.add(issuerType);
				}
			}
			fund.setIssureTypes(fdIssures);
		}
		return fund;
	}

	public List<NewFundDto> getFundWithUnitValue() {
		SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
		NewFundDao dao = new NewFundDao();
		List<Fund> funds = dao.getFundWithUnitValue();
		List<NewFundDto> dtos = new ArrayList<NewFundDto>();
		for (Fund fund : funds) {
			NewFundDto dto = new NewFundDto();
			dto.setId(fund.getId());
			dto.setCode(fund.getFundCode());
			dto.setName(fund.getFundName());
			dto.setUnitValue(fund.getUnitValue());
			if (fund.getUpdateDate() != null)
				dto.setUpdateDate(format.format(fund.getUpdateDate()));
			dtos.add(dto);
		}
		return dtos;
	}

}
